class Level extends egret.Sprite {
	public static PHASE_IN_PROGRESS: number;
	public static PHASE_LEVEL_PASSED: number;
	public static PHASE_LEVEL_FAILED: number;
	public static AI_BASIC: number;
	public static AI_ADVANCED: number;
	public static MAX_CELLS: number;
	public static MAX_FENCES: number;
	public static BmpBack: any;

	private m_game: Game = null;
	private _pause: boolean = false;
	private _maxPower: number = 0;
	private _cpuTurnPeriod: number = 0;
	private _intervalKey: number = 0;
	private _isBlackType: boolean = false;
	private _enable: boolean = false;
	private _userCellType: number = Cell.TYPE_GREEN;
	private linkSprite: egret.Sprite = null;
	private cellSprite: egret.Sprite = null;
	private _linkList: Array<Link> = null;
	// private _SafeStr_143: number = Cell.TYPE_BLACK;
	private _fenceList: Array<Fence> = null;
	private _SafeStr_141: number = 0;
	private _levelName: string = null;
	private _cellList: Array<Cell> = null;

	public constructor(game: Game, name: string = "", maxPower: number = 200) {
		super();
		this.m_game = game;
		this._levelName = name;
		this._maxPower = maxPower;
		this._cellList = new Array();
		this._linkList = new Array();
		this._fenceList = new Array();
		this.linkSprite = new egret.Sprite();
		this.cellSprite = new egret.Sprite();
		this.addChild(this.linkSprite);
		this.addChild(this.cellSprite);
		this._cpuTurnPeriod = 100;
		this.startTime(true);
	}

	public get maxPower(): number {
		return (this._maxPower);
	}

	public set maxPower(power: number) {
		power = (power);
		var cell: Cell;
		this._maxPower = (power);
		var i: number = 0;
		while (i < this._cellList.length) {
			cell = this._cellList[i];
			cell.maxPower = power;
			i++;
		}
	}

	private linkPeriod() {
		var link: Link;
		var orig: Cell;
		var dest: Cell;
		var cut: boolean;
		var i: number = 0;
		while (i < this._linkList.length) {
			link = this._linkList[i];
			orig = link.getOrigCell();
			dest = link.getDestCell();
			if (orig.type != this._userCellType) {
				if ((orig.power < Cell.MIN_PANIC_POWER)) {
					link.cutAt(1);
				}
				if (((orig.type == dest.type) && (link.isAttached()))) {
					cut = false;
					if (orig.type == Cell.TYPE_PURPLE) {
						cut = ((dest.power / 2) > orig.power);
					}
					else {
						cut = (dest.power > 10);
					}

					if (cut) {
						if ((dest.power + link.power) <= orig.power) {
							link.cutAt(0);
						}
						else {
							link.cutAt(0.5);
						}
					}
				}
				if (((orig.type == Cell.TYPE_PURPLE) && (link.isAttached()))) {
					if (((dest.getGiveUpPower() < link.power) && (this.getLinkBetween(dest, orig) == null))) {
						link.cutAt(0);
					}
				}
			}
			i++;
		}
	}

	private getLinkBetween(orig: Cell, dest: Cell): Link {
		var link: Link;
		var i: number = 0;
		while (i < this._linkList.length) {
			link = this._linkList[i];
			if ((((link.getOrigCell() == orig) && (link.getDestCell() == dest)) && (!(link.isCut())))) {
				return link;
			}
			i++;
		}
		return (null);
	}

	private cellSupplyPeriod(cellType: number) {

		var tmpOrig: Cell;
		var tmpDest: Cell;
		var dx: number = 0;
		var dy: number = 0;
		var len: number = 0;
		var i: number = 0;
		var j: number = 0;
		var orig: Cell;
		var dest: Cell;
		var minLen: number = 10000;
		i = (0);
		while (i < this._cellList.length) {
			tmpOrig = this._cellList[i];
			if (((tmpOrig.type == cellType) && (tmpOrig.numOrigLinks < tmpOrig.maxOrigLinks))) {
				j = (0);
				while (j < this._cellList.length) {
					tmpDest = this._cellList[j];
					if (((((tmpDest.type == tmpOrig.type) && (this.getLinkBetween(tmpDest, tmpOrig) == null)) && (this.getLinkBetween(tmpOrig, tmpDest) == null)) && (!(this.isFenceBetween(tmpOrig, tmpDest))))) {
						dx = (tmpDest.x - tmpOrig.x);
						dy = (tmpDest.y - tmpOrig.y);
						len = Math.sqrt(((dx * dx) + (dy * dy)));
						if (((len < minLen) && (((tmpOrig.power - Link.getRequiredPower(len)) - 10) > tmpDest.power))) {
							minLen = len;
							orig = tmpOrig;
							dest = tmpDest;
						}
					}
					j++;
				}
			}
			i++;
		}
		if (((orig) && (dest))) {
			this.addLinkBetween(orig, dest);
		}
	}

	public delCell(cell: Cell) {
		var i: number = (this._cellList.indexOf(cell));
		if (i >= 0) {
			this._cellList.splice(i, 1);
			this.cellSprite.removeChild(cell);
		}
	}

	/**计算交点**/
	private getIntersection(p11x: number, p11y: number, p12x: number, p12y: number, p21x: number, p21y: number, p22x: number, p22y: number): egret.Point {
		var found: boolean;
		var resX: number = 0;
		var resY: number = 0;
		/********a=a2-a1;b=b2-b1**********/
		var z: number = ((p12y - p11y) * (p21x - p22x)) - ((p21y - p22y) * (p12x - p11x));

		var ca: number = ((p12y - p11y) * (p21x - p11x)) - ((p21y - p11y) * (p12x - p11x));
		var cb: number = ((p21y - p11y) * (p21x - p22x)) - ((p21y - p22y) * (p21x - p11x));

		/**平行或者共线**/
		if (z == 0) {
			return null;
		}
		var ua: number = (ca / z);
		var ub: number = (cb / z);
		resX = (p11x + ((p12x - p11x) * ub));
		resY = (p11y + ((p12y - p11y) * ub));

		if (((0 <= ua) && (ua <= 1)) && (0 <= ub) && (ub <= 1)) {
			if (!((ua == 0) || (ua == 1) || (ub == 0) || (ub == 1))) {
				return (new egret.Point(resX, resY));
			}
		}
		return null;
	}

	public addFence(x1: number, y1: number, x2: number, y2: number): Fence {
		if (this._fenceList.length >= Level.MAX_FENCES) {
			return (null);
		}
		var fence: Fence = new Fence(x1, y1, x2, y2);
		this.cellSprite.addChild(fence);
		this._fenceList.push(fence);
		return (fence);
	}

	public newAchievement(id: number) {
		id = (id);
		this.m_game.newAchievement(id);
	}

	public destruct() {
		this.startTime(false);
		if (this.parent) {
			this.parent.removeChild(this);
		}
		this.clear();
	}

	public getUserCellType(): number {
		return (this._userCellType);
	}

	public addCell(x: number, y: number, cellType: number, power: number, maxPower: number = 999): Cell {
		if (this._cellList.length >= Level.MAX_CELLS) {
			return null;
		}
		var cell: Cell = new Cell(this, cellType, power, maxPower);
		cell.x = x;
		cell.y = y;
		if (this._pause) {
			cell.suspend();
		}
		this.cellSprite.addChild(cell);
		this._cellList.push(cell);
		if (cellType == Cell.TYPE_BLACK) {
			this._isBlackType = true;
		}
		return cell;
	}

	public delLink(link: Link) {
		var i: number = (this._linkList.indexOf(link));
		if (i >= 0) {
			this._linkList.splice(i, 1);
			this.linkSprite.removeChild(link);
		}
	}

	public get levelName(): string {
		return (this._levelName);
	}

	public suspend() {
		var cell: Cell;
		this._pause = true;
		var i: number = 0;
		while (i < this._cellList.length) {
			cell = this._cellList[i];
			cell.suspend();
			i++;
		}
	}

	public onLinkAttached(link: Link) {
		this.m_game.onLinkAttached(link);
	}

	private cellAttackPeriod(cellType: number) {
		var tmpOrig: Cell;
		var tmpDest: Cell;
		var dx: number = 0;
		var dy: number = 0;
		var len: number = 0;
		var i: number = 0;
		var j: number = 0;
		var orig: Cell;
		var dest: Cell;
		var minLen: number = 10000;
		i = (0);
		while (i < this._cellList.length) {
			tmpOrig = this._cellList[i];
			if (((tmpOrig.type == cellType) && (tmpOrig.numOrigLinks < tmpOrig.maxOrigLinks))) {
				j = (0);
				while (j < this._cellList.length) {
					tmpDest = this._cellList[j];
					if ((((!(tmpDest.type == tmpOrig.type)) && (this.getLinkBetween(tmpOrig, tmpDest) == null)) && (!(this.isFenceBetween(tmpOrig, tmpDest))))) {
						dx = (tmpDest.x - tmpOrig.x);
						dy = (tmpDest.y - tmpOrig.y);
						len = Math.sqrt(((dx * dx) + (dy * dy)));
						if (this.getLinkBetween(tmpDest, tmpOrig) != null) {
							len = (len / 2);
						}
						if (((len < minLen) && ((tmpOrig.power - 10) > Link.getRequiredPower(len)))) {
							minLen = len;
							orig = tmpOrig;
							dest = tmpDest;
						}
					}
					j++;
				}
			}
			i++;
		}
		if (((orig) && (dest))) {
			this.addLinkBetween(orig, dest);
		}
	}

	public set cpuTurnPeriod(period: number) {

		this._cpuTurnPeriod = period;
	}

	public addLinkBetween(orig: Cell, dest: Cell): boolean {
		if (this.getLinkBetween(orig, dest) != null) {
			return (false);
		}
		if (this.isFenceBetween(orig, dest)) {
			return (false);
		}
		var inverseLink: Link = this.getLinkBetween(dest, orig);
		var link: Link = new Link(this, orig, dest);
		this._linkList.push(link);
		this.linkSprite.addChild(link);
		if (inverseLink) {
			if (orig.type == dest.type) {
				inverseLink.cutAt(1);
			}
			if (!inverseLink.isCut()) {
				inverseLink.setSplitLink(link);
			}
		}
		return (true);
	}

	private clear() {
		var cell: Cell;
		var fence: Fence;
		while (this._cellList.length > 0) {
			cell = this._cellList[0];
			cell.destruct();
			cell = null;
		}
		while (this._fenceList.length > 0) {
			fence = this._fenceList[0];
			this.delFence(fence);
			fence.destruct();
			fence = null;
		}
	}

	public cutLink(x1: number, y1: number, x2: number, y2: number) {
		var link: Link;
		var p21x: number = 0;
		var p21y: number = 0;
		var p22x: number = 0;
		var p22y: number = 0;
		var res: egret.Point;
		var foundLink: Link;
		var resX: number = 0;
		var resY: number = 0;
		var i: number = 0;
		while (i < this._linkList.length) {
			link = this._linkList[i];
			p21x = link.getOrigAnchor().x;
			p21y = link.getOrigAnchor().y;
			p22x = link.getDestAnchor().x;
			p22y = link.getDestAnchor().y;
			res = this.getIntersection(x1, y1, x2, y2, p21x, p21y, p22x, p22y);
			if ((!(res == null) && (link.getOrigCell().type == this._userCellType))) {
				foundLink = link;
				foundLink.cutAtPoint(res.x, res.y);
			}
			i++;
		}
		if (foundLink) {
			this.m_game.clearTutorial();
			// this.m_game.newAchievement(Achievements.ID_CUT);
		}
	}

	public getTotalPowerOf(cellType: number): number {
		cellType = (cellType);
		var cell: Cell;
		var total: number = 0;
		var i: number = 0;
		while (i < this._cellList.length) {
			cell = this._cellList[i];
			if (cell.type == cellType) {
				total = ((total + cell.power));
			}
			i++;
		}
		return (total);
	}

	public isFenceBetween(orig: Cell, dest: Cell): boolean {
		var fence: Fence;
		var dx: number = 0;
		var dy: number = 0;
		var ang: number = 0;
		var x1: number = 0;
		var y1: number = 0;
		var x2: number = 0;
		var y2: number = 0;
		var EXT_LEN: number = (10);
		var i: number = 0;
		while (i < this._fenceList.length) {
			fence = this._fenceList[i];
			dx = (fence.x2 - fence.x1);
			dy = (fence.y2 - fence.y1);
			ang = Math.atan2(dy, dx);
			x1 = fence.x1 - (Math.cos(ang) * EXT_LEN);
			y1 = fence.y1 - (Math.sin(ang) * EXT_LEN);
			x2 = fence.x2 + (Math.cos(ang) * EXT_LEN);
			y2 = fence.y2 + (Math.sin(ang) * EXT_LEN);
			if (this.getIntersection(orig.x, orig.y, dest.x, dest.y, x1, y1, x2, y2) != null) {
				return (true);
			}
			i++;
		}
		return (false);
	}

	public getCode(): string {
		var cell: Cell;
		var fence: Fence;
		var code: string = "";
		var checkSum: number = (((((this._cellList.length + this._fenceList.length) + this._maxPower) + this._SafeStr_141) + this._cpuTurnPeriod));
		var isUserCell: boolean;
		var isEnemyCell: boolean;
		code = String((((((((((this._cellList.length + ",") + this._fenceList.length) + ",") + this._maxPower) + ",") + this._SafeStr_141) + ",") + this._cpuTurnPeriod) + ","));
		var i: number = 0;
		i = (0);
		while (i < this._cellList.length) {
			cell = this._cellList[i];
			code = (code + String((((((((cell.type + ",") + cell.power) + ",") + (cell.x)) + ",") + (cell.y)) + ",")));
			checkSum = ((checkSum + (((cell.type + cell.power) + (cell.x)) + (cell.y))));
			if (cell.type == Cell.TYPE_GREEN) {
				isUserCell = true;
			}
			else {
				if (cell.type != Cell.TYPE_GREY) {
					isEnemyCell = true;
				}
			}
			i++;
		}
		i = (0);
		while (i < this._fenceList.length) {
			fence = this._fenceList[i];
			code = (code + String(((((((((fence.x1) + ",") + (fence.y1)) + ",") + (fence.x2)) + ",") + (fence.y2)) + ",")));
			checkSum = ((checkSum + ((((fence.x1) + (fence.y1)) + (fence.x2)) + (fence.y2))));
			i++;
		}
		code = (code + String(checkSum));
		return (((isUserCell) && (isEnemyCell)) ? code : null);
	}

	private update() {
		var j: number = 0;
		var dx: number = 0;
		var dy: number = 0;
		var len: number = 0;
		var ang: number = 0;
		var value: number = 0;
		var orig: Cell;
		var dest: Cell;
		//边界增量
		var borderDelta: number = 5;
		var i: number = 0;
		while (i < this._cellList.length) {
			orig = this._cellList[i];
			if ((orig.x - orig.radius()) < 0) {
				orig.addMoveDelta(0, borderDelta);
			}
			if ((orig.x + orig.radius()) > GUI.MAX_X) {
				orig.addMoveDelta(180, borderDelta);
			}
			if ((orig.y - orig.radius()) < 20) {
				orig.addMoveDelta(90, borderDelta);
			}
			if ((orig.y + orig.radius()) > (GUI.MAX_Y - 30)) {
				orig.addMoveDelta(-90, borderDelta);
			}
			j = (0);
			j = ((i + 1));
			while (j < this._cellList.length) {
				dest = this._cellList[j];
				dx = (dest.x - orig.x);
				dy = (dest.y - orig.y);
				len = Math.sqrt(((dx * dx) + (dy * dy)));
				if (((orig.radius() + dest.radius()) + 40) > len) {
					ang = dest.getAngleTo(orig);
					value = (((orig.radius() + dest.radius()) > len) ? 20 : (200 / len));
					orig.addMoveDelta(ang, value);
					dest.addMoveDelta((ang + 180), value);
				}
				j++;
			}
			i++;
		}
	}

	public delFence(fence: Fence) {
		var i: number = (this._fenceList.indexOf(fence));
		if (i >= 0) {
			this._fenceList.splice(i, 1);
			this.cellSprite.removeChild(fence);
		}
	}

	public get cpuTurnPeriod(): number {
		return (this._cpuTurnPeriod);
	}

	public initFromCode(code: string): boolean {
		var cellType: number = 0;
		var power: number = 0;
		var x: number = 0;
		var y: number = 0;
		var x1: number = 0;
		var y1: number = 0;
		var x2: number = 0;
		var y2: number = 0;
		var sub: Array<string> = code.split(",");
		var numCells: number = parseInt(((<string>sub.shift())));
		var numFences: number = parseInt(((<string>sub.shift())));
		this._maxPower = parseInt(((<string>sub.shift())));
		this._SafeStr_141 = parseInt(((<string>sub.shift())));
		this._cpuTurnPeriod = parseInt(((<string>sub.shift())));
		var expectedSum: number = (((((numCells + numFences) + this._maxPower) + this._SafeStr_141) + this._cpuTurnPeriod));
		while (((sub.length > 0) && (numCells > 0))) {
			cellType = parseInt(((<string>sub.shift())));
			power = parseInt(((<string>sub.shift())));
			x = parseInt(((<string>sub.shift())));
			y = parseInt(((<string>sub.shift())));
			this.addCell(x, y, cellType, power, this._maxPower);
			expectedSum = ((expectedSum + (((cellType + power) + x) + y)));
			numCells--;
		}
		while (((sub.length > 0) && (numFences > 0))) {
			x1 = parseInt(((<string>sub.shift())));
			y1 = parseInt(((<string>sub.shift())));
			x2 = parseInt(((<string>sub.shift())));
			y2 = parseInt(((<string>sub.shift())));
			this.addFence(x1, y1, x2, y2);
			expectedSum = ((expectedSum + (((x1 + y1) + x2) + y2)));
			numFences--;
		}
		var checkSum: number = parseInt(((<string>sub.shift())));
		if (checkSum != expectedSum) {
			this.clear();
			return (false);
		}
		return (true);
	}

	private startTime(enabled: boolean) {
		if (enabled) {
			if (this._intervalKey == 0) {
				this._intervalKey = (egret.setInterval(this.update, this, 1000));
			}
		}
		else {
			if (this._intervalKey != 0) {
				egret.clearInterval(this._intervalKey);
				this._intervalKey = (0);
			}
		}
	}

	public onCpuTurn() {
		this.cellAttackPeriod(Cell.TYPE_RED);
		this.cellAttackPeriod(Cell.TYPE_BLACK);
		this.cellAttackPeriod(Cell.TYPE_PURPLE);
		this.cellSupplyPeriod(Cell.TYPE_PURPLE);
		this.linkPeriod();
	}

	/**游戏进度**/
	public getGamePhase(): number {
		var cell: Cell;
		var _local_1: number = (-1);
		var someUserCells: boolean;
		var inProgressYet: boolean;
		var i: number = 0;
		while (i < this._cellList.length) {
			cell = this._cellList[i];
			if (cell.type == this._userCellType) {
				someUserCells = true;
			}
			if (((!(cell.type == _local_1)) && (!(cell.type == Cell.TYPE_GREY)))) {
				if (_local_1 == -1) {
					_local_1 = (cell.type);
				}
				else {
					inProgressYet = true;
				}
			}
			i++;
		}
		if (!someUserCells) {
			return (Level.PHASE_LEVEL_FAILED);
		}
		return ((inProgressYet) ? Level.PHASE_IN_PROGRESS : Level.PHASE_LEVEL_PASSED);
	}

	public pause(enabled: boolean) {
		var cell: Cell;
		var link: Link;
		var i: number = 0;
		if (this._enable == enabled) {
			return;
		}
		this._enable = enabled;
		this.startTime(enabled);
		i = (0);
		while (i < this._cellList.length) {
			cell = this._cellList[i];
			cell.pause(enabled);
			i++;
		}
		i = (0);
		while (i < this._linkList.length) {
			link = this._linkList[i];
			link.pause(enabled);
			i++;
		}
	}

}

Level.PHASE_IN_PROGRESS = 0;
Level.PHASE_LEVEL_PASSED = 1;
Level.PHASE_LEVEL_FAILED = 2;
Level.AI_BASIC = 0;
Level.AI_ADVANCED = 1;
Level.MAX_CELLS = 30;
Level.MAX_FENCES = 50;
// Level.BmpBack = Level_BmpBack;

